#pragma once
#include <QLabel>
#include <QMainWindow>
#include <QMap>
#include <vector>

#include "ui_MyNotepad.h"
#include "SearchAndReplace.h"
#include "Goto.h"
class MyNotepad : public QMainWindow {
    Q_OBJECT

public:
    using SearchDir = SearchAndReplace::SearchDir;
    using ReplaceType = SearchAndReplace::ReplaceType;

    MyNotepad(QWidget* parent = nullptr);
    ~MyNotepad();

private:
    // 初始光标位置，从1开始计数
    struct CursorPos {
        int line = 1;
        int column = 1;
    };

    // 状态栏信息，包括占位组件，版本号、光标位置、缩放比例
    struct StatusLabelInfo {
        enum SIZE { LABEL_NUM = 4 };                              // 状态栏组件数量
        enum LABELINDEX { PLACEHOLDER, VERSION, CURSOR, SCALE };  // 状态栏索引顺序
        const std::vector<int> label_width = {
            0,
            100,
            100,
            100,
        };                      // 状态栏组件宽度
        CursorPos cursor_pos;   // 光标位置
        int scale_ratio = 100;  // 缩放比例
    };

    Ui_MyNotepad* ui;
    QString currentFile;  // 表示窗口当前已经关联的包含路径的文件
    bool isSaved;         // 表示当前文件是否已经保存

    // 给底部添加的状态栏对象，一共4个
    // 第一个占位，第二个显示版本号，第三个显示光标位置，第四显示缩放百分比
    QLabel* statusLabel[StatusLabelInfo::LABEL_NUM] = {nullptr};
    StatusLabelInfo statusInfo;           // 记录状态栏相关信息
    SearchAndReplace* pSearchAndReplace;  // 查找和替换窗口类指针
    Goto* pGoto;                          // 跳转窗口类指针

private slots:
    // 窗口菜单中的槽函数
    void on_NewAction_triggered();
    void on_OpenAction_triggered();
    void on_SaveAction_triggered();
    void on_SaveAsAction_triggered();
    void on_QuitAction_triggered();
    void on_StatusBarAction_triggered(bool checked);
    void on_ReplaceAction_triggered();
    void on_FindAction_triggered();
    void on_ZoomInAction_triggered();
    void on_ZoomOutAction_triggered();
    void on_ZoomResetAction_triggered();
    void on_GotoAction_triggered();

    // 文本编辑控件的槽函数
    void on_textEdit_textChanged();
    void on_textEdit_cursorPositionChanged();

    // 接收到查找信号时的槽函数，第一个参数表示查找str，第二个参数表示查找方向
    void on_ReceiveSearchInfo(QString str, SearchDir dir);
    // 接收到替换信号时候的槽函数，第一个参数为查找str，第二个参数为替换str，第三个为替换类型Once or All
    void on_ReceiveReplaceInfo(QString sStr, QString rStr, ReplaceType type);
    // 接收到Goto转到信号时的槽函数，参数为行数
    void on_ReceiveGotoInfo(int line);

private:
    // 所有的connect函数
    void connectAll();
    // 根据状态更新窗口标题
    void updateWindowsTitle();
    // 初始化状态栏
    void initStatusLabel();
    // 反初始化状态栏
    void unInitStatusLable();
    // 更新状态栏中的光标位置
    void updateStatusLabelCursor();
    // 更新状态栏中的缩放比例
    void updateStatusLabelScale();
    // 更新状态栏中的占位组件，主要是根据窗口大小更新其宽度
    void updateStatusLabelPlaceHolder();
    
    // 新建、打开、退出时需要对当前状态进行检查，如果有未保存的更改提示用户更改
    void checkSaved();

protected:
    // 相应相关事件
    void resizeEvent(QResizeEvent* event);
    void keyPressEvent(QKeyEvent* event);
    void closeEvent(QCloseEvent* event);

    // 将内容输出到文件,updCurrFile用于标志是否要更新当前文件名（区分保存和另存）
    void outputToFile(QString fileName, bool updCurrFile = false);
};